package com.hui.demo.shiro;

import com.hui.demo.shiro.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;

import java.util.ArrayList;
import java.util.List;

public class ShiroTest {

    public static void main(String[] args) {
        new DAO().createUser("tom", "123");
        User user = new User();
        user.setName("tom");
        user.setPassword("123");

        if (login(user)) {
            System.out.println("登录成功");
        } else{
            System.out.println("登录失败");
        }
    }

    public static void main2 (String[] args) {
        // 用户
        User zhang3 = new User();
        zhang3.setName("zhang3");
        zhang3.setPassword("12345");

        User li4 = new User();
        li4.setName("li4");
        li4.setPassword("abcde");

        User wang5 = new User();
        wang5.setName("wang5");
        wang5.setPassword("wrongpassword");

        List<User> userList = new ArrayList<>();

        userList.add(zhang3);
        userList.add(li4);
        userList.add(wang5);

        // 角色
        String roleAdmin = "admin";
        String roleProductManager ="productManager";
        List<String> roles = new ArrayList<>();
        roles.add(roleAdmin);
        roles.add(roleProductManager);
        // 权限
        String permitAddProduct = "addProduct";
        String permitAddOrder = "addOrder";
        List<String> permits = new ArrayList<>();
        permits.add(permitAddProduct);
        permits.add(permitAddOrder);

        // 登录
        for (User user : userList) {
            if (login(user)) {
                System.out.printf("%s 登录成功，密码：%s", user.getName(), user.getPassword());
                // 判断用户角色
                for (String role : roles) {
                    if(hasRole(user, role)) {
                        System.out.printf("%s\t 拥有角色: %s\t%n",user.getName(),role);
                    } else {
                        System.out.printf("%s\t 没有角色: %s\t%n",user.getName(),role);
                    }
                }
                // 判断用户权限
                for (String permit : permits) {
                    if(login(user)) {
                        if(isPermitted(user, permit)) {
                            System.out.printf("%s\t 拥有权限: %s\t%n",user.getName(),permit);
                        } else {
                            System.out.printf("%s\t 不拥有权限: %s\t%n",user.getName(),permit);
                        }
                    }
                }
            } else {
                System.out.printf("%s 登录失败，密码：%s", user.getName(), user.getPassword());
            }
        }
    }

    private static boolean login (User user) {
        Subject subject =getSubject(user);
        // 如果已经登录，退出
        if (subject.isAuthenticated()) {
            subject.logout();
        }
        // 封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword());
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            return false;
        }
        return subject.isAuthenticated();
    }

    // 判断用户是否拥有角色
    private static boolean hasRole (User user, String role) {
        Subject subject = getSubject(user);
        return subject.hasRole(role);
    }

    // 判断用户是否拥有权限
    private static boolean isPermitted (User user, String permit) {
        Subject subject = getSubject(user);
        return subject.isPermitted(permit);
    }

    private static Subject getSubject (User user) {
        // 加载配置文件，并获取工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:config/shiro.ini");
        // 获取安全管理者实例
        SecurityManager manager = factory.getInstance();
        // 将安全管理者放入全局对象
        SecurityUtils.setSecurityManager(manager);
        // 全局对象通过安全管理者生成Subject对象
        Subject subject = SecurityUtils.getSubject();

        return subject;
    }
}
